﻿using AutoMapper;
using Foundation.AutoMapper;
using Foundation.Caching;
using Foundation.DistributeLock.RedLock;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using IConfigurationProvider = AutoMapper.IConfigurationProvider;

namespace Dyao.Bus.Extensions.Configuration
{
    public static class HostSetupExtensions
    {
        public static IHost Setup(this IHost host)
        {
            var serviceProvider = host.Services;
            // 注入自定义服务
            serviceProvider.UseObjectMapping();
            serviceProvider.UseRedLock();
            serviceProvider.UseCachingCollector();

            PreLoadAssemblies();

            return host;
        }


        public static void UseObjectMapping(this IServiceProvider rootServiceProvider)
        {
            using (var scope = rootServiceProvider.CreateScope())
            {
                var options = scope.ServiceProvider.GetRequiredService<IOptionsMonitor<Foundation.AutoMapper.AutoMapperOptions>>().CurrentValue;

                void ConfigureAll(Foundation.AutoMapper.IAutoMapperConfigurationContext ctx)
                {
                    foreach (var configurator in options.Configurators)
                    {
                        configurator(ctx);
                    }
                }

                void ValidateAll(IConfigurationProvider config)
                {
                    foreach (var profileType in options.ValidatingProfiles)
                    {
                        config.AssertConfigurationIsValid();
                    }
                }

                var mapperConfiguration = new MapperConfiguration(mapperConfigurationExpression =>
                {
                    ConfigureAll(new AutoMapperConfigurationContext(mapperConfigurationExpression, scope.ServiceProvider));
                });

                ValidateAll(mapperConfiguration);

                scope.ServiceProvider.GetRequiredService<MapperAccessor>().Mapper = mapperConfiguration.CreateMapper();
            }
        }

        /// <summary>
        /// 分布式锁
        /// </summary>
        /// <param name="rootServiceProvider"></param>
        public static void UseRedLock(this IServiceProvider rootServiceProvider)
        {
            var configration = rootServiceProvider.GetService<IConfiguration>();
            var multiplexers = configration.GetSection(nameof(RedLockOptions)).Get<RedLockOptions>().Multiplexers;
            var loggerFactory = rootServiceProvider.GetService<ILoggerFactory>();
            RedLockOptionsBuilder.Build(builder =>
            {
                return builder.Multiplexers(multiplexers)
                .LoggerFactory(loggerFactory);
            });
        }

        /// <summary>
        /// 添加缓存方法
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="scope"></param>
        /// <returns></returns>
        public static void UseCachingCollector(this IServiceProvider rootServiceProvider)
        {
            var methodCache = rootServiceProvider.GetService<MethodMatcherCache>();
            methodCache.GetCandidatesMethods();
        }

        /// <summary>
        /// 预先加载程序集 避免动态加载
        /// </summary>
        public static void PreLoadAssemblies()
        {
            var list = new List<Type>()
            {
                typeof(Dyao.Book.BusContract.PreloadContract)
            };
        }
    }
}
